// echo aux function only, should not compile alone.
// -r:"../../Backend/System.IO.FileSystem.dll"

//! 编译方法，目前来说只能是自己改上面那行字，把缺的东西都补齐，之后送命令提示符或者用python脚本编译。
//! windows就是一坨shit……连通配符都不支持……不然我至少能写出类似 dotnet C:\Program Files\dotnet\sdk\*\Roslyn\bincore\csc.dll 这样的语法

// -r:"../../The Scroll of Taiwu_Data/Managed/Mono.Cecil.dll" -r:"../../The Scroll of Taiwu_Data/Managed/System.Core.dll"   -r:"../../The Scroll of Taiwu_Data/Managed/System.Composition.AttributedModel.dll" -r:"../../Backend/System.Runtime.dll"
/**
 *  Everyone's Unity Game Plugin
 *  Copyright (C) 2022 Neutron3529
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */
//! 这是一个自带文档注释的Mod，虽然代码很shit，但里面有不少注释，或许会对之后准备玩过月逻辑的人有帮助。
//! 所有文档注释会用//!开头，请注意搜索
//! 首先是前后端，前端对后端的调用会先被塞进 ProcessMethodCall，之后分发给对应domain的CallMethod，由CallMethod进行进一步的分发。借助这一点，我们可以快速找到前端调用究竟是在使用哪个函数。
using System;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Collections.Generic;
using static Utils.Logger;

using Config.EventConfig;
using GameData.Domains.TaiwuEvent;
using GameData.Domains.TaiwuEvent.Enum;

namespace Neutron3529.ChaosEvents {
    public partial class ChaosEvents : EventPackage {
        public 云游道.云游道 E00(){
            var o=new 云游道.云游道();
            // logger("init TEPTT_EP done.");
            var taiwuEvent = GameData.Domains.DomainManager.TaiwuEvent.GetEvent("c6f33e5d-2ff7-4789-b2c6-b39179269669");
            // logger("obtain taiwuEvent: "+taiwuEvent.EventGuid);
            var lst=taiwuEvent.EventConfig.EventOptions.ToList();
            foreach(var op in o.EventOptions){
                lst.Insert(lst.Count-1, op);
            }
            taiwuEvent.EventConfig.EventOptions=lst.ToArray();
            // taiwuEvent.AddOption(new ValueTuple<string, string>("70b4d45d-ba15-423d-b94e-b40e348eb9c0","Option_35290001"));
            // taiwuEvent.AddOption(new ValueTuple<string, string>("70b4d45d-ba15-423d-b94e-b40e348eb9c0","Option_35290002"));
            // logger("event inserted.");
            return o;
        }
    }
    namespace 云游道 {
        public class 云游道 : EventContainer {
            public 云游道() :base("Prof.云游道", "70b4d45d-ba15-423d-b94e-b40e348eb9c0"){
                var op1=new TaiwuEventOption {
                    OptionKey = "Option_35290001",
                    OnOptionSelect = new Func<string>(this.OnOption1Select),
                    OnOptionVisibleCheck = new Func<bool>(this.OnCheckEventCondition),
                    OnOptionAvailableCheck = new Func<bool>(this.OnCheckEventCondition),
                    GetReplacedContent = new Func<string>(this.Desc(0)),
                    GetExtraFormatLanguageKeys = new Func<List<string>>(this.GetExtraFormatLanguageKeys)
                };
                op1.SetContent("（天予不取，反受其咎！......）");
                var op2=new TaiwuEventOption {
                    OptionKey = "Option_35290002",
                    OnOptionSelect = new Func<string>(this.OnOption2Select),
                    OnOptionVisibleCheck = new Func<bool>(this.OnCheckEventCondition),
                    OnOptionAvailableCheck = new Func<bool>(this.OnCheckEventCondition),
                    GetReplacedContent = new Func<string>(this.Desc(1)),
                    GetExtraFormatLanguageKeys = new Func<List<string>>(this.GetExtraFormatLanguageKeys)
                };
                op2.SetContent("（塞翁失马，焉知非福？......）");
                var op3=new TaiwuEventOption {
                    OptionKey = "Option_35290003",
                    OnOptionSelect = new Func<string>(this.OnOption3Select),
                    OnOptionVisibleCheck = new Func<bool>(this.OnCheckEventCondition),
                    OnOptionAvailableCheck = new Func<bool>(this.OnCheckEventCondition),
                    GetReplacedContent = new Func<string>(this.Desc(2)),
                    GetExtraFormatLanguageKeys = new Func<List<string>>(this.GetExtraFormatLanguageKeys)
                };
                op3.SetContent("（开坛做法，夺天造化！......）");
                var op4=new TaiwuEventOption {
                    OptionKey = "Option_35290004",
                    OnOptionSelect = new Func<string>(this.OnOption4Select),
                    OnOptionVisibleCheck = new Func<bool>(this.OnCheckEventCondition),
                    OnOptionAvailableCheck = new Func<bool>(this.OnCheckEventCondition),
                    GetReplacedContent = new Func<string>(this.Desc(3)),
                    GetExtraFormatLanguageKeys = new Func<List<string>>(this.GetExtraFormatLanguageKeys)
                };
                op4.SetContent("（开坛做法，予人前程......）");
                this.EventOptions = new TaiwuEventOption[] {
                    op1,op2,op3,op4
                };
            }
            // public override bool OnCheckEventCondition()=>true;//this.ArgBox!=null && this.ArgBox.GetCharacter("CharacterId") != null && this.ArgBox.GetCharacter("CharacterId").GetFeatureIds() != null && GameData.Domains.DomainManager.Taiwu.GetTaiwu() != null && GameData.Domains.DomainManager.Taiwu.GetTaiwu().GetFeatureIds() != null && !this.ArgBox.GetCharacter("CharacterId").GetFeatureIds().Exists((x)=>Config.CharacterFeature.Instance[x]==null) && !GameData.Domains.DomainManager.Taiwu.GetTaiwu().GetFeatureIds().Exists((x)=>Config.CharacterFeature.Instance[x]==null);

            // private string OnOption1GetReplacedContent()=>string.Empty;

            private string OnOption1Select()=>GatherGood(true);
            private string OnOption2Select()=>GatherGood(false);
            private string OnOption3Select()=>KaiGood(true);
            private string OnOption4Select()=>KaiGood(false);
            private string GatherGood(bool flag){
                var ArgBox=this.EventOptions[flag?0:1].ArgBox;
                var character = ArgBox.GetCharacter("CharacterId");
                var taiwuChar = GameData.Domains.DomainManager.Taiwu.GetTaiwu();
                // int badFeatureCount = GameData.Domains.TaiwuEvent.EventHelper.EventHelper.GetBadFeatureCount(character);

                var taiwuFeatureIds = taiwuChar.GetFeatureIds();
                var  charFeatureIds = character.GetFeatureIds();
                var prev=new List<short>(charFeatureIds);
                prev.Sort();

                var taiwuDiscard = Discard(taiwuFeatureIds,flag);
                var  charDiscard = Discard(charFeatureIds,!flag);

                var td=Merge(taiwuFeatureIds,charDiscard, flag);
                var cd=Merge(charFeatureIds,taiwuDiscard,!flag);

                SortAddRange(taiwuFeatureIds,cd,!flag);
                SortAddRange(charFeatureIds,td,flag);

                var context=GameData.Domains.DomainManager.TaiwuEvent.MainThreadDataContext;
                taiwuChar.SetFeatureIds(taiwuFeatureIds, context);
                character.SetFeatureIds(charFeatureIds, context);

                var curr=new List<short>(charFeatureIds);
                curr.Sort();
                if(prev.SequenceEqual(curr)){
                    return Goto("“我感觉……好像变好了，又好像没变化”\n<color=#lightgrey>（<Character key=CharacterId str=Name/>并没有被<Character key=RoleTaiwu str=Name/>的法事所影响）</color>","（搞错了啊……）",flag?0:1); // 无效的修改
                }
                if(flag){
                    return Goto("“我感觉……啊巴啊巴啊……”\n<color=#lightgrey>（<Character key=CharacterId str=Name/>的正面特性已然被<Character key=RoleTaiwu str=Name/>的法事所掠夺）</color>","（不错不错……）",flag?0:1); // NPC的坏结果，玩家的好结果
                }else{
                    return Goto("“我感觉……不错不错，挺美好的……”\n<color=#lightgrey>（<Character key=RoleTaiwu str=Name/>借助法事，将身上的一切正面特性赋予了<Character key=CharacterId str=Name/>）</color>","（啊巴啊巴啊……）",flag?0:1); // NPC的好结果，玩家的坏结果
                }
            }
            private string KaiGood(bool flag){
                var ArgBox=this.EventOptions[flag?2:3].ArgBox;
                var character = ArgBox.GetCharacter("CharacterId");
                var taiwuChar = GameData.Domains.DomainManager.Taiwu.GetTaiwu();
                // int badFeatureCount = GameData.Domains.TaiwuEvent.EventHelper.EventHelper.GetBadFeatureCount(character);

                var taiwuFeatureIds = taiwuChar.GetFeatureIds();
                var  charFeatureIds = character.GetFeatureIds();
                var prev=new List<short>(charFeatureIds);
                prev.Sort();

                var taiwuDiscard = Discard(taiwuFeatureIds,flag);
                var  charDiscard = Discard(charFeatureIds,!flag);

                var td=GMerge(taiwuFeatureIds,charDiscard, flag);
                var cd=GMerge(charFeatureIds,taiwuDiscard,!flag);

                SortAddRange(taiwuFeatureIds,cd,!flag);
                SortAddRange(charFeatureIds,td,flag);

                var context=GameData.Domains.DomainManager.TaiwuEvent.MainThreadDataContext;
                taiwuChar.SetFeatureIds(taiwuFeatureIds, context);
                character.SetFeatureIds(charFeatureIds, context);

                var curr=new List<short>(charFeatureIds);
                curr.Sort();
                if(prev.SequenceEqual(curr)){
                    return Goto("“我感觉……好像变好了，又好像没变化”\n<color=#lightgrey>（<Character key=CharacterId str=Name/>并没有被<Character key=RoleTaiwu str=Name/>的法事所影响）</color>","（搞错了啊……）",flag?2:3); // 无效的修改
                }
                if(flag){
                    return Goto("“我感觉……啊巴啊巴啊……”\n<color=#lightgrey>（<Character key=CharacterId str=Name/>的正面特性已然被<Character key=RoleTaiwu str=Name/>的法事所掠夺）</color>","（不错不错……）",flag?2:3); // NPC的坏结果，玩家的好结果
                }else{
                    return Goto("“我感觉……不错不错，挺美好的……”\n<color=#lightgrey>（<Character key=RoleTaiwu str=Name/>借助法事，将身上的一切正面特性赋予了<Character key=CharacterId str=Name/>）</color>","（啊巴啊巴啊……）",flag?2:3); // NPC的好结果，玩家的坏结果
                }
            }
            private static Dictionary<short, short> Discard(List<short> orig, bool keep_good){
                var featureIds = new Dictionary<short, short>();
                var len=orig.Count;
                for (int index = len - 1; index >= 0; index--) {
                    short featureId = orig[index];
                    var featureCfg = Config.CharacterFeature.Instance[featureId];
                    if (featureCfg.CanBeExchanged && featureCfg.Level>0 ^ keep_good) { // keep_good=true, 将坏特性（包括0级的先天畸形）移除
                        featureIds[featureCfg.MutexGroupId]=featureId;
                        orig.RemoveAt(index);
                    }
                }
                return featureIds;
            }
            private static List<short> Merge(List<short> orig, Dictionary<short, short> featureIds, bool keep_good){
                var lst=new List<short>();
                var len=orig.Count;
                for (int index = len - 1; index >= 0; index--) {
                    short featureId = orig[index];
                    var featureCfg = Config.CharacterFeature.Instance[featureId];
                    short mid;
                    if (featureIds.TryGetValue(featureCfg.MutexGroupId,out mid)) {
                        var mcfg=Config.CharacterFeature.Instance[mid];
                        if ((mcfg.Level>featureCfg.Level) ^ keep_good){ // keep_good=true时, mid.level<=featureId.level,
                            // orig[index]=featureId;
                            lst.Add(mid);
                        } else {
                            orig[index]=mid;
                            lst.Add(featureId);
                        }
                        featureIds.Remove(featureCfg.MutexGroupId);
                    }
                }
                orig.AddRange(featureIds.Values);
                return lst;
            }
            private static List<short> GMerge(List<short> orig, Dictionary<short, short> featureIds, bool keep_good){
                var lst=new List<short>();
                var len=orig.Count;
                for (int index = len - 1; index >= 0; index--) {
                    short featureId = orig[index];
                    var featureCfg = Config.CharacterFeature.Instance[featureId];
                    short mid;
                    if (featureIds.TryGetValue(featureCfg.MutexGroupId,out mid)) {
                        var mcfg=Config.CharacterFeature.Instance[mid];
                        short keep,ret;
                        if ((mcfg.Level>featureCfg.Level) ^ keep_good){ // keep_good=true时, mid.level<=featureId.level,
                            keep=featureId;
                            ret=mid;
                        } else {
                            keep=mid;
                            ret=featureId;
                        }
                        featureIds.Remove(featureCfg.MutexGroupId);
                        for(int guard=0;guard<3;guard++){
                            if(ret<1 || keep>Config.CharacterFeature.Instance.Count-2){break;}
                            var kcfg=Config.CharacterFeature.Instance[keep+1];
                            var rcfg=Config.CharacterFeature.Instance[ret-1];
                            if(kcfg.MutexGroupId!=rcfg.MutexGroupId || ((kcfg.Level>0) ^ keep_good)){
                                break;
                            }
                            keep++;
                            ret--;
                        }
                        orig[index]=keep;
                        lst.Add(ret);
                    }
                }
                orig.AddRange(featureIds.Values);
                return lst;
            }
            private static void SortAddRange(List<short> orig, List<short> featureIds, bool keep_good){
                var len=orig.Count;
                for (int index = len - 1; index >= 0; index--) {
                    short featureId = orig[index];
                    var featureCfg = Config.CharacterFeature.Instance[featureId];
                    if (featureCfg.CanBeExchanged && featureCfg.Level>0 ^ keep_good) { // keep_good=true, 将坏特性（包括0级的先天畸形）移除
                        featureIds.Add(featureId);
                        orig.RemoveAt(index);
                    }
                }
                featureIds.Sort();
                orig.AddRange(featureIds);
            }
        }
    }
}
